package com.easyUtils.utils.jwtUtil;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;

/**
 * JWT 工具类，支持配置文件配置密钥和过期时间。
 */
@Slf4j
public class JwtUtil<T> {

    private final SecretKey secretKey;
    private final long expirationTime;
    private static final ObjectMapper MAPPER = new ObjectMapper();
    private final Class<T> entityClass;

    public JwtUtil(String secretKeyStr, long expirationTime, Class<T> entityClass) {
        this.secretKey = Keys.hmacShaKeyFor(secretKeyStr.getBytes(StandardCharsets.UTF_8));
        this.expirationTime = expirationTime;
        this.entityClass = entityClass;
        log.info("JWT工具类初始化完成，过期时间：{}毫秒", expirationTime);
    }

    public String createToken(T entity) {
        log.info("创建 JWT Token");
        try {
            Date now = new Date();
            return Jwts.builder()
                    .setPayload(MAPPER.writeValueAsString(entity))
                    .setIssuedAt(now)
                    .setExpiration(new Date(now.getTime() + expirationTime))
                    .signWith(secretKey, SignatureAlgorithm.HS256)
                    .compact();
        } catch (Exception e) {
            log.error("创建Token失败", e);
            throw new RuntimeException("创建Token失败: " + e.getMessage(), e);
        }
    }

    public T parseToken(String token) {
        log.info("解析 JWT Token");
        try {
            Claims claims = Jwts.parserBuilder()
                    .setSigningKey(secretKey)
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
            return MAPPER.readValue(MAPPER.writeValueAsString(claims), entityClass);
        } catch (Exception e) {
            log.error("解析Token失败", e);
            throw new RuntimeException("解析Token失败: " + e.getMessage(), e);
        }
    }

    public boolean isValid(String token) {
        try {
            Jwts.parserBuilder()
                    .setSigningKey(secretKey)
                    .build()
                    .parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            log.info("Token验证失败: {}", e.getMessage());
            return false;
        }
    }
}

/**
 * 使用说明
 * 配置文件
 * jwt:
 *   secret-key: your-secure-secret-key-256-bit-long
 *   expiration-time: 86400000
 *
 * 配置类
 *   @Configuration
 * public class JwtConfig {
 *     @Bean
 *     public JwtUtil<User> userJwtUtil(JwtProperties properties) {
 *         return new JwtUtil<>(
 *             properties.getSecretKey(),
 *             properties.getExpirationTime(),
 *             User.class
 *         );
 *     }
 * }
 * 使用示例
 * @Service
 * public class UserService {
 *     private final JwtUtil<User> jwtUtil;
 *
 *     @Autowired
 *     public UserService(JwtUtil<User> jwtUtil) {
 *         this.jwtUtil = jwtUtil;
 *     }
 *
 *     public String generateToken(User user) {
 *         return jwtUtil.createToken(user);
 *     }
 *
 *     public User validateAndGetUser(String token) {
 *         if (jwtUtil.isValid(token)) {
 *             return jwtUtil.parseTokenToObject(token);
 *         }
 *         throw new RuntimeException("Invalid token");
 *     }
 * }
 */